///////////////////////////////////////////////////////////////////////////
// Programa VIDA. 
//
// Esto no es un ejemplo de buena programacion ni esta optimizado
// en velocidad, solo tiene por proposito ilustrar sobre el algoritmo
// de VIDA. Es decir, esta pensado para ser facil de entender.
//
///////////////////////////////////////////////////////////////////////////
#include <stdio.h>             // funciones de impresion
#include <stdlib.h>            // funciones aleatorias
#include <unistd.h>            // si queremos poner delays

#define FILAS 80
#define COLS 80 

#define CELULA 1               // No modificar

char pantalla[FILAS][COLS];    // Pantalla del ciclo anterior
char pantalla2[FILAS][COLS];   // Pantalla del ciclo actual

///////////////////////////////////////////////////////////////////////////
//      Inicializa la matriz de pantaala y pone las celulas iniciales
///////////////////////////////////////////////////////////////////////////
// void IniciarPantalla(void)
// {
// unsigned int col, fila;
// 
// for(col=0; col<COLS; col++)                // Exploramos todo el mundo
// 	for(fila=0; fila<FILAS; fila++)
// 		pantalla2[fila][col]=0;              // Pomemos el mundo a 0 (vacio)
// 
// for(int n=0; n<POBLACION_INICIAL; n++)     // Siembra celulas aleatoriamente
// 	{
// 	fila=random(FILAS);
// 	col=random(COLS);
// 	pantalla2[fila][col]=CELULA;
// 	}
// }


///////////////////////////////////////////////////////////////////////////
//  Cuenta los vecinos a una celula dada
///////////////////////////////////////////////////////////////////////////
unsigned char CuentaVecinos(long fila, long col)
{
unsigned char vecinos=0;
long arriba,
	  abajo,
	  izquierda,
	  derecha;

  // calcula las adyacentes (mundo toroidal)
arriba=fila-1;
if(arriba<0) arriba=FILAS-1;

abajo=fila+1;
if(abajo==FILAS) abajo=0;

izquierda=col-1;
if(izquierda<0) izquierda=COLS-1;

derecha=col+1;
if(derecha==COLS) derecha=0;

if(pantalla[arriba][izquierda]==CELULA) vecinos++;
if(pantalla[arriba][col]==CELULA) vecinos++;
if(pantalla[arriba][derecha]==CELULA) vecinos++;

if(pantalla[fila][izquierda]==CELULA) vecinos++;
if(pantalla[fila][derecha]==CELULA) vecinos++;

if(pantalla[abajo][izquierda]==CELULA) vecinos++;
if(pantalla[abajo][col]==CELULA) vecinos++;
if(pantalla[abajo][derecha]==CELULA) vecinos++;
return(vecinos);
}


///////////////////////////////////////////////////////////////////////////
//   Calcula si la celulas se reproducen, viven o mueren
///////////////////////////////////////////////////////////////////////////
void CicloVida(void)
{
unsigned int col, fila;

  for(col=0; col<COLS; col++)              // Exploramos todo el mundo
for(fila=0; fila<FILAS; fila++)
		{
		unsigned char vecinos;

		vecinos=CuentaVecinos(fila,col);   // Cuenta los vecinos de esa casilla

		if(pantalla[fila][col]==0 &&       // Si en una casilla vacia y
			vecinos==3)                     // hay tres vecinos
				pantalla2[fila][col]=CELULA; // nace una celula

		if(pantalla[fila][col]==CELULA)
		    {
			if (vecinos>1 && vecinos<4)  // tiene mas de dos vecinos y  menos de cuatro
				{
				pantalla2[fila][col]=CELULA;
				} // la celula sobrevive
			else pantalla2[fila][col]=0;
			}
				
		}
		
  for(col=0; col<COLS; col++)                // Actualizamos el mundo
for(fila=0; fila<FILAS; fila++)
		pantalla[fila][col]=pantalla2[fila][col];     
}


// void DespedidaYCierre(void)
// {
// clrscr();
// cprintf("\r\n\r\n\r\n");
// cprintf("                IMPLEMENTACION DEL PROGRAMA VIDA\r\n");
// cprintf("\r\n");
// cprintf("   Bueno, esto es todo. Este programa esta en modo texto y no tiene\r\n");
// cprintf(" ninguna optimizacion en velocidad, ni siquiera la implementacion\r\n");
// cprintf(" esta pensada para ser veloz. Su unico proposito es ilustrar sobre\r\n");
// cprintf(" algoritmo del programa. De las multiples implementaciones de este\r\n");
// cprintf(" esta es seguramente la mas sencilla de entender.\r\n\r\n");
// cprintf("   Programado por SILICOn, y puesto bajo licencia GNU. Modificalo y\r\n");
// cprintf(" distribuyelo como gustes, pero no te olvides de citar la fuente.\r\n");
// cprintf("\r\n");
// cprintf("\r\n");
// cprintf("   NOTA: Es mi primera excursion en la vida artificial.\r\n");
// }

int leerDatosIniciales()
{
  int fila, col;
  char inputc;
  for(col=0; col<COLS; col++)
	{
	for(fila=0; fila<FILAS; fila++)
	  {
	  inputc = getchar();
	  switch (inputc) {
		case ' ': pantalla[fila][col]=0;
				  break;
		case '@': pantalla[fila][col]=CELULA;
				  break;
		default:  fprintf(stderr, "Error en el archivo de entrada: fila %d contiene un caracter invalido en la columna %d \n", fila, col);
				  return(-1);
		}
	  }
	if(getc(stdin)!='\n')
	  {
	  fprintf(stderr, "Error en el archivo de entrada: fila %d no termina en \\n \n", fila);
	  return(-1);
	  }
	}
	return(0);
}

void grabarMatriz(int iteracion)
{
  int fila, col;
  char *filename = (char *)malloc(20);
  FILE *archivo;
  
  sprintf(filename, "out/salida%03d.txt",iteracion);
  archivo = fopen(filename, "w");
  for(col=0; col<COLS; col++)   
	{
	for(fila=0; fila<FILAS; fila++)
		fputc(pantalla[fila][col]?'@':' ', archivo);
	fputc('\n', archivo);
	}
  fclose(archivo);
}

///////////////////////////////////////////////////////////////////////////
// La funcion principal
///////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
unsigned int ciclo;        // Ciclo de vida actual

leerDatosIniciales(); //vienen por stdin
for(ciclo=0;ciclo<400;ciclo++)              // iteramos unas 400 veces
	{
	CicloVida();              // Calculamos un ciclo de vida
	grabarMatriz(ciclo);  // Sacamos el resultado por stdout
	}
/*DespedidaYCierre();*/
return(0);
}


















